Carmen Martín Turrero
Date : 10/05/2022
library(lubridate)
library(ggplot2)
library(GoFKernel)
library(latex2exp)
library(dplyr)
library(plotly)
Exercise 1
The number of particles emitted by a radioactive source during a
fixed interval of time (∆t = 10 s) follows a Poisson distribution on the
parameter µ. The number of particles observed during consecutive time
intervals is: 4, 1, 3, 1 and 3
- suppose a uniform prior distribution for the parameter µ
- determine and draw the posterior distribution for µ, given the
data
- evaluate mean, median and variance, both analytically and
numerically in R
# Data
t.int <- 10 #s
x.observed <- c(4, 1, 3, 1, 3)
# Uniform prior
x <- seq(0, 10, by=0.01)
U.prior <- dgamma(x, 1, 0)
# the posterior is a gamma function with parameters:
U.alpha <- sum(x.observed) + 1
U.lambda <- length(x.observed)
U.posterior <- dgamma(x, U.alpha, U.lambda)
uni.df <- data.frame(x = x, prior = U.prior+0.1, posterior = U.posterior)
uni.plot <- ggplot() +
geom_line(data = uni.df, aes(x = x, y = prior, color = 'Uniform prior'), linetype =2 , size = 0.8) +
geom_line(data = uni.df, aes(x = x, y = posterior, color = 'Posterior'), size = 0.8) +
labs(title = 'Particles emitted by radioactive source during 10s', subtitle = 'Poisson Distribution', x = 'n', y = 'PDF') +
guides(color=guide_legend(NULL, order = 5)) +
scale_colour_brewer(palette = "Paired")
uni.plot

# Analytically
aU.mean <- (U.alpha-1)/U.lambda
aU.var <- (U.alpha-1)/(U.lambda**2)
# Numerically
nU.mean <- integrate(function(x) {x*dgamma(x, U.alpha, U.lambda)}, 0, 10)
Ex2 <- integrate(function(x) {(x**2)*dgamma(x, U.alpha, U.lambda)}, 0, 10)
nU.var <- Ex2$value - (nU.mean$value)**2
# We use the quantile to obtain the median
nU.median <- qgamma(0.5, U.alpha, U.lambda)
message('Analytically: mean = ', aU.mean, ', variance = ', aU.var)
Analytically: mean = 2.4, variance = 0.48
message('Numerically: mean = ', round(nU.mean$value,2), ', variance = ', round(nU.var,2))
Numerically: mean = 2.6, variance = 0.52
message('Median = ', round(nU.median,2))
Median = 2.53
- suppose a Jeffrey’s prior for the parameter µ
- determine and draw the posterior distribution for µ, given the
data
- evaluate mean, median and variance, both analytically and
numerically in R
# Jeffreys prior
x <- seq(0, 10, by=0.01)
J.prior <- dgamma(x, 0.5, 0)
# the posterior is a gamma function with parameters:
J.alpha <- sum(x.observed) + 0.5
J.lambda <- length(x.observed)
J.posterior <- dgamma(x, J.alpha, J.lambda)
jef.df <- data.frame(x = x, prior = J.prior, posterior = J.posterior)
jef.plot <- ggplot() +
geom_line(data = jef.df, aes(x = x, y = prior, color = 'Jeffreys prior'), linetype =2 , size = 0.8) +
geom_line(data = jef.df, aes(x = x, y = posterior, color = 'Posterior'), size = 0.8) +
labs(title = 'Particles emitted by radioactive source during 10s', subtitle = 'Poisson Distribution', x = 'n', y = 'PDF') +
guides(color=guide_legend(NULL, order = 5)) +
scale_colour_brewer(palette = "Paired")
jef.plot

# Analytically
aJ.mean <- (J.alpha-0.5)/J.lambda
aJ.var <- (J.alpha-0.5)/(J.lambda**2)
# Numerically
nJ.mean <- integrate(function(x) {x*dgamma(x, J.alpha, J.lambda)}, 0, 10)
Ex2 <- integrate(function(x) {(x**2)*dgamma(x, J.alpha, J.lambda)}, 0, 10)
nJ.var <- Ex2$value - (nJ.mean$value)**2
# We use the quantile to obtain the median
nJ.median <- qgamma(0.5, J.alpha, J.lambda)
message('Analytically: mean = ', aJ.mean, ', variance = ', aJ.var)
Analytically: mean = 2.4, variance = 0.48
message('Numerically: mean = ', round(nJ.mean$value,2), ', variance = ', round(nJ.var,2))
Numerically: mean = 2.5, variance = 0.5
message('Median = ', round(nJ.median,2))
Median = 2.43
- evaluate a 95% credibility interval for the results obtained with
both priors. Compare the result with that obtained using a normal
approximation for the posterior distribution, with the same mean and
standard deviation
# Most probable value
max.valueU <- x[which.max(U.posterior)]
max.valueJ <- x[which.max(J.posterior)]
# Credibility intervals
U.x1 <- qgamma(0.025, U.alpha, U.lambda)
U.x2 <- qgamma(0.975, U.alpha, U.lambda)
print(paste0('Uniform prior credibility interval of [', round(U.x1,2),', ', round(U.x2,2),']'))
[1] "Uniform prior credibility interval of [1.38, 4.19]"
J.x1 <- qgamma(0.025, J.alpha, J.lambda)
J.x2 <- qgamma(0.975, J.alpha, J.lambda)
print(paste0('Jeffreys prior credibility interval of [', round(J.x1,2),', ', round(J.x2,2),']'))
[1] "Jeffreys prior credibility interval of [1.31, 4.06]"
G.x1 <- qnorm(0.025, aU.mean, sqrt(aU.var))
G.x2 <- qnorm(0.975, aU.mean, sqrt(aU.var))
print(paste0('Normal approximation credibility interval of [', round(G.x1,2),', ', round(G.x2,2),']'))
[1] "Normal approximation credibility interval of [1.04, 3.76]"
Exercise 2
Given the problem of the lightouse discussed last week, study the
case in which both the position along the shore (α) and the distance out
at sea (β) are unknown.
As discussed during the lectures, it is reasonable to assign a
uniform likelihood on the azimuth angle \(\theta_k\) , given the angle is uniform
over \(\pm \pi/2\), the probability
is:
\[\begin{equation}
P(X |\alpha,\beta) = \frac{1}{\pi}
\end{equation}\]
\(\theta_k\) is connected to the
distances \(\alpha\) and \(\beta\) through the relation
\[\begin{equation}
x_k - \alpha = \beta \tan \theta_k
\end{equation}\]
We can perform a change of variable in order to compute \(P(x|\alpha,\beta)\):
\[\begin{equation}
P(x|\alpha,\beta) = P(\theta|\alpha,\beta)\abs{\frac{d\theta}{dx}}
\end{equation}\]
Since \(x=\beta \tan\theta +
\alpha\), by differenciating \(\theta\) w.r.t. \(x\), we obtain:
\[\begin{equation}
\abs{\frac{d\theta}{dx}} = \frac{\beta^2 + (x - \alpha)^2}{\beta}
\end{equation}\]
And, as a consequence:
\[\begin{equation}
P(x|\alpha,\beta) = \frac{1}{\pi}\frac{\beta}{\beta^2 + (x - \alpha)^2}
\end{equation}\]
This pdf corresponds to the Cauchy distribution.
Now, since we do not know \(\alpha\)
nor \(\beta\), we estimate their prior.
As \(\alpha \perp \beta\), the
posterior is of the form:
\[\begin{equation}
P(\alpha,\beta |{x_k}) \propto P({x_k}|\alpha,\beta)P(\alpha)P(\beta)
\end{equation}\]
Assuming \(\alpha\) is uniform over
the segment \([x_{min},\ x_{max}]\),
i.e. \(p(\alpha) = \frac{1}{x_{max} -
x_{min}}\); and \(\beta\) is
uniform over the segment \([0,
y_{max}]\), i.e. \(p(\beta) =
\frac{1}{y_{max}}\). Then, the posterior is proportional to the
likelihood:
\[\begin{equation}
P(\alpha,\beta |{x_k}) \propto P({x_k}|\alpha,\beta)
\end{equation}\]
For the likelihood, we consider each sample of the data to be iid
and, therefore:
\[\begin{equation}
P({x_k}|\alpha,\beta) = \prod_{k=1}^{N} P(x_k|\alpha,\beta)
\end{equation}\]
# Generate dataset
set.seed(4183)
# true values
a <- 10; b <- 10;
N <- 200
theta <- runif(N, -pi/2, pi/2)
x.k <- a*tan(theta) + a
#Set the problem data
x.min <- -2000 #m
x.max <- 2000 #m
y.max <- 5000 #m
alphas <- seq(x.min, x.max, 20)
betas <- seq(0, y.max, 20)
# Logarithmic posterior
log.posterior <- function(x.k, alph, bet) {
sum(log((bet)/(pi*(bet**2 + (x.k-alph)**2))))
}
f.aux <- function (a, b){ log.posterior(x.k, a, b) }
# Evaluate for all possible parameter combinations
log.grid <- outer(alphas, betas, Vectorize(f.aux))
# Posteriors shape
# Individual posterior (known alpha)
log.posterior.ind <- function (x.k, b) {
Vectorize(function(a_) {
sum(log(b/(pi*(b**2 + (x.k-a_)**2))))
})
}
lpos <- log.posterior.ind(x.k, a)
# Normalize and exponentiate
shape.posterior <- function (x, lpos) {
log.alphas <- lpos(x)
log.maxalpha <- max(log.alphas)
return (exp(log.alphas - log.maxalpha))
}
# Obtain the results
grid.values <- matrix(shape.posterior(log.grid, lpos),
nrow = length(alphas), ncol = length(betas))
fig <- plot_ly(type = 'surface',x = alphas, y = betas, z = grid.values)
fig <- layout(fig, scene = list(yaxis = list(title = 'Height (m)',range=c(1900,2100)), xaxis = list(title = 'Location (m)',range = c(-2000,-1900)), zaxis = list(title = 'PDF')))
fig
max = which(grid.values == max(grid.values), arr.ind = TRUE)
max.alpha <- alphas[max[1,2]]
max.beta <- betas[max[1,1]]
message('The position of the lighthouse is ', (max.alpha)/1000,'km along the shore and ', max.beta/1000, 'km out at sea.')
The position of the lighthouse is -1.98km along the shore and 2.02km out at sea.
Exercise 3
Given the Signal over Background example discussed last week, analyze
and discuss the following cases:
- vary the sampling resolution of used to generate the data, keeping
the same sampling range xdat <- seq(from=-7w, to=7w,
by=0.5*w) • change the resolution w = {0.1, 0.25, 1, 2, 3} • Check the
effect on the results
# Generative model
signal <- function(x, a, b, x0, w, t) {
t * (a*exp(-((x-x0)**2)/(2*w**2)) + b)
}
# Define model parameters
x0 <- 0 # Signal peak
w.range <- c(0.1, 0.25, 1, 2, 3) # Signal width
A.true <- 2 # Signal amplitude
B.true <- 1 # Background amplitude
Delta.t <- 5 # Exposure time
# Sampling grid for computing posterior
alim <- c(0.0, 4.0)
blim <- c(0.5, 1.5)
Nsamp <- 100
uniGrid <- seq(from=1/(2*Nsamp),
to=1-1/(2*Nsamp), by=1/Nsamp)
delta_a <- diff(alim )/ Nsamp
delta_b <- diff(blim )/ Nsamp
a <- alim[1] + diff(alim )* uniGrid
b <- blim[1] + diff(blim )* uniGrid
# Log posterior
log.post <- function(d, x, a, b, x0, w, t) {
if(a<0 || b <0) {return(-Inf )} # the effect of the prior
sum(dpois(d, lambda=signal(x, a, b, x0, w, t), log=TRUE))
}
# Generate the observed data
set.seed(123)
for (w in w.range){
xdat <- seq(from=-7*w, to=7*w, by=0.5*w)
s.true <- signal(xdat , A.true , B.true , x0, w, Delta.t)
ddat <- rpois(length(s.true), s.true)
xplot <- seq(from=min(xdat), to=max(xdat), by=0.05*w)
splot <- signal(xplot , A.true , B.true , x0, w, Delta.t)
options(repr.plot.width=14, repr.plot.height=10) #to set graph size
par(mfrow=c(1,2))
plot(xplot , splot , xlab="x", ylab="Signal+Background counts", ylim=c(2, 24))
#par(new=TRUE)
xdat.off <- xdat - 0.25
lines(xdat.off, ddat , type='s',col='firebrick3', lwd=2,xlim=range(xplot), ylim=range(c(splot , ddat )))
# Compute log unnormalized posterior , z = ln Pˆ*(a,b|D), on a regular grid
z <- matrix(data=NA , nrow=length(a), ncol=length(b))
for(j in 1:length(a)) {
for(k in 1:length(b)) {
z[j,k] <- log.post(ddat , xdat , a[j], b[k], x0, w, Delta.t)
}
}
z <- z - max(z) # set maximum to zero
# Plot unnormalized 2D posterior as contours.
contour(a, b, exp(z),
nlevels = 5,
labcex = 0.5,
lwd = 2,
xlab="amplitude , A",
ylab="background , B")
abline(v=2,h=1,col="grey")
}





NA
NA
- change the ratio A/B used to simulate the data (keeping both
positive in accordance with the prior) • Check the effect on the
results
# Define model parameters
x0 <- 0 # Signal peak
w.range <- 1 # Signal width
A.true <- 4 # Signal amplitude
B.true <- 1 # Background amplitude
Delta.t <- 5 # Exposure time
xdat <- seq(from=-7*w, to=7*w, by=0.5*w)
s.true <- signal(xdat , A.true , B.true , x0, w, Delta.t)
ddat <- rpois(length(s.true), s.true)
xplot <- seq(from=min(xdat), to=max(xdat), by=0.05*w)
splot <- signal(xplot , A.true , B.true , x0, w, Delta.t)
options(repr.plot.width=14, repr.plot.height=10) #to set graph size
par(mfrow=c(1,2))
plot(xplot , splot , xlab="x", ylab="Signal+Background counts", ylim=c(0, 40))
#par(new=TRUE)
xdat.off <- xdat - 0.25
lines(xdat.off, ddat , type='s',col='firebrick3', lwd=2,xlim=range(xplot), ylim=range(c(splot , ddat )))
# Compute log unnormalized posterior , z = ln Pˆ*(a,b|D), on a regular grid
z <- matrix(data=NA , nrow=length(a), ncol=length(b))
for(j in 1:length(a)) {
for(k in 1:length(b)) {
z[j,k] <- log.post(ddat , xdat , a[j], b[k], x0, w, Delta.t)
}
}
z <- z - max(z) # set maximum to zero
# Plot unnormalized 2D posterior as contours.
contour(a, b, exp(z),
nlevels = 4,
labcex = 0.5,
lwd = 2,
xlab="amplitude , A",
ylab="background , B",
xlim = c(0,5))
abline(v=4,h=1,col="grey")

NA
NA
LS0tDQp0aXRsZTogIkxhYm9yYXRvcnkgMDUiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCmVkaXRvcl9vcHRpb25zOiANCiAgbWFya2Rvd246IA0KICAgIHdyYXA6IDcyDQotLS0NCg0KQ2FybWVuIE1hcnTDrW4gVHVycmVybw0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KRGF0ZSA6IDEwLzA1LzIwMjINCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCmBgYHtyfQ0KbGlicmFyeShsdWJyaWRhdGUpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KEdvRktlcm5lbCkNCmxpYnJhcnkobGF0ZXgyZXhwKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkocGxvdGx5KQ0KYGBgDQoNCi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQ0KDQojIyBFeGVyY2lzZSAxDQoNClRoZSBudW1iZXIgb2YgcGFydGljbGVzIGVtaXR0ZWQgYnkgYSByYWRpb2FjdGl2ZSBzb3VyY2UgZHVyaW5nIGEgZml4ZWQNCmludGVydmFsIG9mIHRpbWUgKOKIhnQgPSAxMCBzKSBmb2xsb3dzIGEgUG9pc3NvbiBkaXN0cmlidXRpb24gb24gdGhlDQpwYXJhbWV0ZXIgwrUuIFRoZSBudW1iZXIgb2YgcGFydGljbGVzIG9ic2VydmVkIGR1cmluZyBjb25zZWN1dGl2ZSB0aW1lDQppbnRlcnZhbHMgaXM6IDQsIDEsIDMsIDEgYW5kIDMNCg0KKGEpIHN1cHBvc2UgYSB1bmlmb3JtIHByaW9yIGRpc3RyaWJ1dGlvbiBmb3IgdGhlIHBhcmFtZXRlciDCtQ0KDQotICAgZGV0ZXJtaW5lIGFuZCBkcmF3IHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIGZvciDCtSwgZ2l2ZW4gdGhlIGRhdGENCi0gICBldmFsdWF0ZSBtZWFuLCBtZWRpYW4gYW5kIHZhcmlhbmNlLCBib3RoIGFuYWx5dGljYWxseSBhbmQNCiAgICBudW1lcmljYWxseSBpbiBSDQoNCmBgYHtyfQ0KIyBEYXRhDQp0LmludCA8LSAxMCAjcw0KeC5vYnNlcnZlZCA8LSBjKDQsIDEsIDMsIDEsIDMpDQoNCiMgVW5pZm9ybSBwcmlvcg0KeCA8LSBzZXEoMCwgMTAsIGJ5PTAuMDEpDQpVLnByaW9yIDwtIGRnYW1tYSh4LCAxLCAwKQ0KDQojIHRoZSBwb3N0ZXJpb3IgaXMgYSBnYW1tYSBmdW5jdGlvbiB3aXRoIHBhcmFtZXRlcnM6DQpVLmFscGhhIDwtIHN1bSh4Lm9ic2VydmVkKSArIDENClUubGFtYmRhIDwtIGxlbmd0aCh4Lm9ic2VydmVkKQ0KDQpVLnBvc3RlcmlvciA8LSBkZ2FtbWEoeCwgVS5hbHBoYSwgVS5sYW1iZGEpDQoNCnVuaS5kZiA8LSBkYXRhLmZyYW1lKHggPSB4LCBwcmlvciA9IFUucHJpb3IrMC4xLCBwb3N0ZXJpb3IgPSBVLnBvc3RlcmlvcikNCg0KdW5pLnBsb3QgPC0gZ2dwbG90KCkgKw0KICBnZW9tX2xpbmUoZGF0YSA9IHVuaS5kZiwgYWVzKHggPSB4LCB5ID0gcHJpb3IsIGNvbG9yID0gJ1VuaWZvcm0gcHJpb3InKSwgbGluZXR5cGUgPTIgLCBzaXplID0gMC44KSArDQogIGdlb21fbGluZShkYXRhID0gdW5pLmRmLCBhZXMoeCA9IHgsIHkgPSBwb3N0ZXJpb3IsIGNvbG9yID0gJ1Bvc3RlcmlvcicpLCBzaXplID0gMC44KSArDQogIGxhYnModGl0bGUgPSAnUGFydGljbGVzIGVtaXR0ZWQgYnkgcmFkaW9hY3RpdmUgc291cmNlIGR1cmluZyAxMHMnLCBzdWJ0aXRsZSA9ICdQb2lzc29uIERpc3RyaWJ1dGlvbicsIHggPSAnbicsIHkgPSAnUERGJykgKw0KICBndWlkZXMoY29sb3I9Z3VpZGVfbGVnZW5kKE5VTEwsIG9yZGVyID0gNSkpICsNCiAgc2NhbGVfY29sb3VyX2JyZXdlcihwYWxldHRlID0gIlBhaXJlZCIpDQoNCnVuaS5wbG90DQpgYGANCg0KYGBge3J9DQojIEFuYWx5dGljYWxseQ0KYVUubWVhbiA8LSAoVS5hbHBoYS0xKS9VLmxhbWJkYQ0KYVUudmFyIDwtIChVLmFscGhhLTEpLyhVLmxhbWJkYSoqMikNCg0KIyBOdW1lcmljYWxseQ0KblUubWVhbiA8LSBpbnRlZ3JhdGUoZnVuY3Rpb24oeCkge3gqZGdhbW1hKHgsIFUuYWxwaGEsIFUubGFtYmRhKX0sIDAsIDEwKQ0KRXgyIDwtIGludGVncmF0ZShmdW5jdGlvbih4KSB7KHgqKjIpKmRnYW1tYSh4LCBVLmFscGhhLCBVLmxhbWJkYSl9LCAwLCAxMCkNCm5VLnZhciA8LSBFeDIkdmFsdWUgLSAoblUubWVhbiR2YWx1ZSkqKjINCg0KIyBXZSB1c2UgdGhlIHF1YW50aWxlIHRvIG9idGFpbiB0aGUgbWVkaWFuDQpuVS5tZWRpYW4gPC0gcWdhbW1hKDAuNSwgVS5hbHBoYSwgVS5sYW1iZGEpDQoNCm1lc3NhZ2UoJ0FuYWx5dGljYWxseTogbWVhbiA9ICcsIGFVLm1lYW4sICcsIHZhcmlhbmNlID0gJywgYVUudmFyKQ0KbWVzc2FnZSgnTnVtZXJpY2FsbHk6IG1lYW4gPSAnLCByb3VuZChuVS5tZWFuJHZhbHVlLDIpLCAnLCB2YXJpYW5jZSA9ICcsIHJvdW5kKG5VLnZhciwyKSkNCm1lc3NhZ2UoJ01lZGlhbiA9ICcsIHJvdW5kKG5VLm1lZGlhbiwyKSkNCmBgYA0KDQooYikgc3VwcG9zZSBhIEplZmZyZXkncyBwcmlvciBmb3IgdGhlIHBhcmFtZXRlciDCtQ0KDQotICAgZGV0ZXJtaW5lIGFuZCBkcmF3IHRoZSBwb3N0ZXJpb3IgZGlzdHJpYnV0aW9uIGZvciDCtSwgZ2l2ZW4gdGhlIGRhdGENCi0gICBldmFsdWF0ZSBtZWFuLCBtZWRpYW4gYW5kIHZhcmlhbmNlLCBib3RoIGFuYWx5dGljYWxseSBhbmQNCiAgICBudW1lcmljYWxseSBpbiBSDQoNCmBgYHtyfQ0KIyBKZWZmcmV5cyBwcmlvcg0KeCA8LSBzZXEoMCwgMTAsIGJ5PTAuMDEpDQpKLnByaW9yIDwtIGRnYW1tYSh4LCAwLjUsIDApDQoNCiMgdGhlIHBvc3RlcmlvciBpcyBhIGdhbW1hIGZ1bmN0aW9uIHdpdGggcGFyYW1ldGVyczoNCkouYWxwaGEgPC0gc3VtKHgub2JzZXJ2ZWQpICsgMC41DQpKLmxhbWJkYSA8LSBsZW5ndGgoeC5vYnNlcnZlZCkNCg0KSi5wb3N0ZXJpb3IgPC0gZGdhbW1hKHgsIEouYWxwaGEsIEoubGFtYmRhKQ0KDQpqZWYuZGYgPC0gZGF0YS5mcmFtZSh4ID0geCwgcHJpb3IgPSBKLnByaW9yLCBwb3N0ZXJpb3IgPSBKLnBvc3RlcmlvcikNCg0KamVmLnBsb3QgPC0gZ2dwbG90KCkgKw0KICBnZW9tX2xpbmUoZGF0YSA9IGplZi5kZiwgYWVzKHggPSB4LCB5ID0gcHJpb3IsIGNvbG9yID0gJ0plZmZyZXlzIHByaW9yJyksIGxpbmV0eXBlID0yICwgc2l6ZSA9IDAuOCkgKw0KICBnZW9tX2xpbmUoZGF0YSA9IGplZi5kZiwgYWVzKHggPSB4LCB5ID0gcG9zdGVyaW9yLCBjb2xvciA9ICdQb3N0ZXJpb3InKSwgc2l6ZSA9IDAuOCkgKw0KICBsYWJzKHRpdGxlID0gJ1BhcnRpY2xlcyBlbWl0dGVkIGJ5IHJhZGlvYWN0aXZlIHNvdXJjZSBkdXJpbmcgMTBzJywgc3VidGl0bGUgPSAnUG9pc3NvbiBEaXN0cmlidXRpb24nLCB4ID0gJ24nLCB5ID0gJ1BERicpICsNCiAgZ3VpZGVzKGNvbG9yPWd1aWRlX2xlZ2VuZChOVUxMLCBvcmRlciA9IDUpKSArDQogIHNjYWxlX2NvbG91cl9icmV3ZXIocGFsZXR0ZSA9ICJQYWlyZWQiKQ0KDQpqZWYucGxvdA0KYGBgDQoNCmBgYHtyfQ0KIyBBbmFseXRpY2FsbHkNCmFKLm1lYW4gPC0gKEouYWxwaGEtMC41KS9KLmxhbWJkYQ0KYUoudmFyIDwtIChKLmFscGhhLTAuNSkvKEoubGFtYmRhKioyKQ0KDQojIE51bWVyaWNhbGx5DQpuSi5tZWFuIDwtIGludGVncmF0ZShmdW5jdGlvbih4KSB7eCpkZ2FtbWEoeCwgSi5hbHBoYSwgSi5sYW1iZGEpfSwgMCwgMTApDQpFeDIgPC0gaW50ZWdyYXRlKGZ1bmN0aW9uKHgpIHsoeCoqMikqZGdhbW1hKHgsIEouYWxwaGEsIEoubGFtYmRhKX0sIDAsIDEwKQ0KbkoudmFyIDwtIEV4MiR2YWx1ZSAtIChuSi5tZWFuJHZhbHVlKSoqMg0KDQojIFdlIHVzZSB0aGUgcXVhbnRpbGUgdG8gb2J0YWluIHRoZSBtZWRpYW4NCm5KLm1lZGlhbiA8LSBxZ2FtbWEoMC41LCBKLmFscGhhLCBKLmxhbWJkYSkNCg0KbWVzc2FnZSgnQW5hbHl0aWNhbGx5OiBtZWFuID0gJywgYUoubWVhbiwgJywgdmFyaWFuY2UgPSAnLCBhSi52YXIpDQptZXNzYWdlKCdOdW1lcmljYWxseTogbWVhbiA9ICcsIHJvdW5kKG5KLm1lYW4kdmFsdWUsMiksICcsIHZhcmlhbmNlID0gJywgcm91bmQobkoudmFyLDIpKQ0KbWVzc2FnZSgnTWVkaWFuID0gJywgcm91bmQobkoubWVkaWFuLDIpKQ0KYGBgDQoNCihjKSBldmFsdWF0ZSBhIDk1JSBjcmVkaWJpbGl0eSBpbnRlcnZhbCBmb3IgdGhlIHJlc3VsdHMgb2J0YWluZWQgd2l0aA0KICAgIGJvdGggcHJpb3JzLiBDb21wYXJlIHRoZSByZXN1bHQgd2l0aCB0aGF0IG9idGFpbmVkIHVzaW5nIGEgbm9ybWFsDQogICAgYXBwcm94aW1hdGlvbiBmb3IgdGhlIHBvc3RlcmlvciBkaXN0cmlidXRpb24sIHdpdGggdGhlIHNhbWUgbWVhbiBhbmQNCiAgICBzdGFuZGFyZCBkZXZpYXRpb24NCg0KYGBge3J9DQojIE1vc3QgcHJvYmFibGUgdmFsdWUgDQptYXgudmFsdWVVIDwtIHhbd2hpY2gubWF4KFUucG9zdGVyaW9yKV0NCm1heC52YWx1ZUogPC0geFt3aGljaC5tYXgoSi5wb3N0ZXJpb3IpXQ0KDQojIENyZWRpYmlsaXR5IGludGVydmFscw0KVS54MSA8LSBxZ2FtbWEoMC4wMjUsIFUuYWxwaGEsIFUubGFtYmRhKSAgIA0KVS54MiA8LSBxZ2FtbWEoMC45NzUsIFUuYWxwaGEsIFUubGFtYmRhKQ0KcHJpbnQocGFzdGUwKCdVbmlmb3JtIHByaW9yIGNyZWRpYmlsaXR5IGludGVydmFsIG9mIFsnLCByb3VuZChVLngxLDIpLCcsICcsIHJvdW5kKFUueDIsMiksJ10nKSkNCg0KSi54MSA8LSBxZ2FtbWEoMC4wMjUsIEouYWxwaGEsIEoubGFtYmRhKSAgIA0KSi54MiA8LSBxZ2FtbWEoMC45NzUsIEouYWxwaGEsIEoubGFtYmRhKQ0KcHJpbnQocGFzdGUwKCdKZWZmcmV5cyBwcmlvciBjcmVkaWJpbGl0eSBpbnRlcnZhbCBvZiBbJywgcm91bmQoSi54MSwyKSwnLCAnLCByb3VuZChKLngyLDIpLCddJykpDQoNCkcueDEgPC0gcW5vcm0oMC4wMjUsIGFVLm1lYW4sIHNxcnQoYVUudmFyKSkNCkcueDIgPC0gcW5vcm0oMC45NzUsIGFVLm1lYW4sIHNxcnQoYVUudmFyKSkNCnByaW50KHBhc3RlMCgnTm9ybWFsIGFwcHJveGltYXRpb24gY3JlZGliaWxpdHkgaW50ZXJ2YWwgb2YgWycsIHJvdW5kKEcueDEsMiksJywgJywgcm91bmQoRy54MiwyKSwnXScpKQ0KDQpgYGANCg0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tDQoNCiMjIEV4ZXJjaXNlIDINCg0KR2l2ZW4gdGhlIHByb2JsZW0gb2YgdGhlIGxpZ2h0b3VzZSBkaXNjdXNzZWQgbGFzdCB3ZWVrLCBzdHVkeSB0aGUgY2FzZQ0KaW4gd2hpY2ggYm90aCB0aGUgcG9zaXRpb24gYWxvbmcgdGhlIHNob3JlICjOsSkgYW5kIHRoZSBkaXN0YW5jZSBvdXQgYXQNCnNlYSAozrIpIGFyZSB1bmtub3duLg0KDQpBcyBkaXNjdXNzZWQgZHVyaW5nIHRoZSBsZWN0dXJlcywgaXQgaXMgcmVhc29uYWJsZSB0byBhc3NpZ24gYSB1bmlmb3JtDQpsaWtlbGlob29kIG9uIHRoZSBhemltdXRoIGFuZ2xlICRcdGhldGFfayQgLCBnaXZlbiB0aGUgYW5nbGUgaXMgdW5pZm9ybQ0Kb3ZlciAkXHBtIFxwaS8yJCwgdGhlIHByb2JhYmlsaXR5IGlzOg0KDQpgYGB7PXRleH0NClxiZWdpbntlcXVhdGlvbn0NClAoWCB8XGFscGhhLFxiZXRhKSA9IFxmcmFjezF9e1xwaX0NClxlbmR7ZXF1YXRpb259DQpgYGANCiRcdGhldGFfayQgaXMgY29ubmVjdGVkIHRvIHRoZSBkaXN0YW5jZXMgJFxhbHBoYSQgYW5kICRcYmV0YSQgdGhyb3VnaA0KdGhlIHJlbGF0aW9uDQoNCmBgYHs9dGV4fQ0KXGJlZ2lue2VxdWF0aW9ufQ0KeF9rIC0gXGFscGhhID0gXGJldGEgXHRhbiBcdGhldGFfaw0KXGVuZHtlcXVhdGlvbn0NCmBgYA0KV2UgY2FuIHBlcmZvcm0gYSBjaGFuZ2Ugb2YgdmFyaWFibGUgaW4gb3JkZXIgdG8gY29tcHV0ZQ0KJFAoeHxcYWxwaGEsXGJldGEpJDoNCg0KYGBgez10ZXh9DQpcYmVnaW57ZXF1YXRpb259DQpQKHh8XGFscGhhLFxiZXRhKSA9IFAoXHRoZXRhfFxhbHBoYSxcYmV0YSlcYWJze1xmcmFje2RcdGhldGF9e2R4fX0NClxlbmR7ZXF1YXRpb259DQpgYGANClNpbmNlICR4PVxiZXRhIFx0YW5cdGhldGEgKyBcYWxwaGEkLCBieSBkaWZmZXJlbmNpYXRpbmcgJFx0aGV0YSQgdy5yLnQuDQokeCQsIHdlIG9idGFpbjoNCg0KYGBgez10ZXh9DQpcYmVnaW57ZXF1YXRpb259DQpcYWJze1xmcmFje2RcdGhldGF9e2R4fX0gPSBcZnJhY3tcYmV0YV4yICsgKHggLSBcYWxwaGEpXjJ9e1xiZXRhfQ0KXGVuZHtlcXVhdGlvbn0NCmBgYA0KQW5kLCBhcyBhIGNvbnNlcXVlbmNlOg0KDQpgYGB7PXRleH0NClxiZWdpbntlcXVhdGlvbn0NClAoeHxcYWxwaGEsXGJldGEpID0gXGZyYWN7MX17XHBpfVxmcmFje1xiZXRhfXtcYmV0YV4yICsgKHggLSBcYWxwaGEpXjJ9DQpcZW5ke2VxdWF0aW9ufQ0KYGBgDQpUaGlzIHBkZiBjb3JyZXNwb25kcyB0byB0aGUgQ2F1Y2h5IGRpc3RyaWJ1dGlvbi4NCg0KTm93LCBzaW5jZSB3ZSBkbyBub3Qga25vdyAkXGFscGhhJCBub3IgJFxiZXRhJCwgd2UgZXN0aW1hdGUgdGhlaXIgcHJpb3IuDQpBcyAkXGFscGhhIFxwZXJwIFxiZXRhJCwgdGhlIHBvc3RlcmlvciBpcyBvZiB0aGUgZm9ybToNCg0KYGBgez10ZXh9DQpcYmVnaW57ZXF1YXRpb259DQpQKFxhbHBoYSxcYmV0YSB8e3hfa30pIFxwcm9wdG8gUCh7eF9rfXxcYWxwaGEsXGJldGEpUChcYWxwaGEpUChcYmV0YSkNClxlbmR7ZXF1YXRpb259DQpgYGANCkFzc3VtaW5nICRcYWxwaGEkIGlzIHVuaWZvcm0gb3ZlciB0aGUgc2VnbWVudCAkW3hfe21pbn0sXCB4X3ttYXh9XSQsDQppLmUuICRwKFxhbHBoYSkgPSBcZnJhY3sxfXt4X3ttYXh9IC0geF97bWlufX0kOyBhbmQgJFxiZXRhJCBpcyB1bmlmb3JtDQpvdmVyIHRoZSBzZWdtZW50ICRbMCwgeV97bWF4fV0kLCBpLmUuICRwKFxiZXRhKSA9IFxmcmFjezF9e3lfe21heH19JC4NClRoZW4sIHRoZSBwb3N0ZXJpb3IgaXMgcHJvcG9ydGlvbmFsIHRvIHRoZSBsaWtlbGlob29kOg0KDQpgYGB7PXRleH0NClxiZWdpbntlcXVhdGlvbn0NClAoXGFscGhhLFxiZXRhIHx7eF9rfSkgXHByb3B0byBQKHt4X2t9fFxhbHBoYSxcYmV0YSkNClxlbmR7ZXF1YXRpb259DQpgYGANCkZvciB0aGUgbGlrZWxpaG9vZCwgd2UgY29uc2lkZXIgZWFjaCBzYW1wbGUgb2YgdGhlIGRhdGEgdG8gYmUgaWlkIGFuZCwNCnRoZXJlZm9yZToNCg0KYGBgez10ZXh9DQpcYmVnaW57ZXF1YXRpb259DQpQKHt4X2t9fFxhbHBoYSxcYmV0YSkgPSBccHJvZF97az0xfV57Tn0gUCh4X2t8XGFscGhhLFxiZXRhKQ0KXGVuZHtlcXVhdGlvbn0NCmBgYA0KYGBge3J9DQojIEdlbmVyYXRlIGRhdGFzZXQNCnNldC5zZWVkKDQxODMpDQojIHRydWUgdmFsdWVzDQphIDwtIDEwOyBiIDwtIDEwOw0KTiA8LSAyMDANCnRoZXRhIDwtIHJ1bmlmKE4sIC1waS8yLCBwaS8yKQ0KeC5rIDwtIGEqdGFuKHRoZXRhKSArIGENCmBgYA0KDQpgYGB7cn0NCiNTZXQgdGhlIHByb2JsZW0gZGF0YQ0KeC5taW4gPC0gLTIwMDAgI20NCngubWF4IDwtIDIwMDAgI20NCnkubWF4IDwtIDUwMDAgI20NCg0KYWxwaGFzIDwtIHNlcSh4Lm1pbiwgeC5tYXgsIDIwKQ0KYmV0YXMgPC0gc2VxKDAsIHkubWF4LCAyMCkNCmBgYA0KDQpgYGB7cn0NCiMgTG9nYXJpdGhtaWMgcG9zdGVyaW9yDQpsb2cucG9zdGVyaW9yIDwtIGZ1bmN0aW9uKHguaywgYWxwaCwgYmV0KSB7DQogIHN1bShsb2coKGJldCkvKHBpKihiZXQqKjIgKyAoeC5rLWFscGgpKioyKSkpKQ0KfQ0KDQpmLmF1eCA8LSBmdW5jdGlvbiAoYSwgYil7IGxvZy5wb3N0ZXJpb3IoeC5rLCBhLCBiKSB9DQoNCiMgRXZhbHVhdGUgZm9yIGFsbCBwb3NzaWJsZSBwYXJhbWV0ZXIgY29tYmluYXRpb25zIA0KbG9nLmdyaWQgPC0gb3V0ZXIoYWxwaGFzLCBiZXRhcywgVmVjdG9yaXplKGYuYXV4KSkNCg0KIyBQb3N0ZXJpb3JzIHNoYXBlDQojIEluZGl2aWR1YWwgcG9zdGVyaW9yIChrbm93biBhbHBoYSkNCmxvZy5wb3N0ZXJpb3IuaW5kIDwtIGZ1bmN0aW9uICh4LmssIGIpIHsNCiAgVmVjdG9yaXplKGZ1bmN0aW9uKGFfKSB7DQogICAgc3VtKGxvZyhiLyhwaSooYioqMiArICh4LmstYV8pKioyKSkpKQ0KICB9KQ0KfQ0KDQpscG9zIDwtIGxvZy5wb3N0ZXJpb3IuaW5kKHguaywgYSkNCg0KIyBOb3JtYWxpemUgYW5kIGV4cG9uZW50aWF0ZQ0Kc2hhcGUucG9zdGVyaW9yIDwtIGZ1bmN0aW9uICh4LCBscG9zKSB7DQogIGxvZy5hbHBoYXMgPC0gbHBvcyh4KQ0KICBsb2cubWF4YWxwaGEgPC0gbWF4KGxvZy5hbHBoYXMpDQogIHJldHVybiAoZXhwKGxvZy5hbHBoYXMgLSBsb2cubWF4YWxwaGEpKQ0KfQ0KDQojIE9idGFpbiB0aGUgcmVzdWx0cw0KZ3JpZC52YWx1ZXMgPC0gbWF0cml4KHNoYXBlLnBvc3Rlcmlvcihsb2cuZ3JpZCwgbHBvcyksIA0KICAgICAgICAgICAgICAgICAgICAgIG5yb3cgPSBsZW5ndGgoYWxwaGFzKSwgbmNvbCA9IGxlbmd0aChiZXRhcykpDQpgYGANCg0KYGBge3J9DQpmaWcgPC0gcGxvdF9seSh0eXBlID0gJ3N1cmZhY2UnLHggPSBhbHBoYXMsIHkgPSBiZXRhcywgeiA9IGdyaWQudmFsdWVzKQ0KZmlnIDwtIGxheW91dChmaWcsIHNjZW5lID0gbGlzdCh5YXhpcyA9IGxpc3QodGl0bGUgPSAnSGVpZ2h0IChtKScscmFuZ2U9YygxOTAwLDIxMDApKSwgeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0xvY2F0aW9uIChtKScscmFuZ2UgPSBjKC0yMDAwLC0xOTAwKSksIHpheGlzID0gbGlzdCh0aXRsZSA9ICdQREYnKSkpDQoNCmZpZw0KYGBgDQoNCg0KYGBge3J9DQoNCm1heCA9IHdoaWNoKGdyaWQudmFsdWVzID09IG1heChncmlkLnZhbHVlcyksIGFyci5pbmQgPSBUUlVFKQ0KbWF4LmFscGhhIDwtIGFscGhhc1ttYXhbMSwyXV0NCm1heC5iZXRhIDwtIGJldGFzW21heFsxLDFdXQ0KbWVzc2FnZSgnVGhlIHBvc2l0aW9uIG9mIHRoZSBsaWdodGhvdXNlIGlzICcsIChtYXguYWxwaGEpLzEwMDAsJ2ttIGFsb25nIHRoZSBzaG9yZSBhbmQgJywgbWF4LmJldGEvMTAwMCwgJ2ttIG91dCBhdCBzZWEuJykNCmBgYA0KDQotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0NCg0KIyMgRXhlcmNpc2UgMw0KDQpHaXZlbiB0aGUgU2lnbmFsIG92ZXIgQmFja2dyb3VuZCBleGFtcGxlIGRpc2N1c3NlZCBsYXN0IHdlZWssIGFuYWx5emUNCmFuZCBkaXNjdXNzIHRoZSBmb2xsb3dpbmcgY2FzZXM6DQoNCihhKSB2YXJ5IHRoZSBzYW1wbGluZyByZXNvbHV0aW9uIG9mIHVzZWQgdG8gZ2VuZXJhdGUgdGhlIGRhdGEsIGtlZXBpbmcNCiAgICB0aGUgc2FtZSBzYW1wbGluZyByYW5nZSB4ZGF0IFw8LSBzZXEoZnJvbT0tNyp3LCB0bz03KncsIGJ5PTAuNVwqdykg4oCiDQogICAgY2hhbmdlIHRoZSByZXNvbHV0aW9uIHcgPSB7MC4xLCAwLjI1LCAxLCAyLCAzfSDigKIgQ2hlY2sgdGhlIGVmZmVjdCBvbg0KICAgIHRoZSByZXN1bHRzDQoNCmBgYHtyfQ0KIyBHZW5lcmF0aXZlIG1vZGVsDQpzaWduYWwgPC0gZnVuY3Rpb24oeCwgYSwgYiwgeDAsIHcsIHQpIHsNCiAgdCAqIChhKmV4cCgtKCh4LXgwKSoqMikvKDIqdyoqMikpICsgYikNCn0NCg0KIyBEZWZpbmUgbW9kZWwgcGFyYW1ldGVycw0KeDAgPC0gMCAjIFNpZ25hbCBwZWFrDQp3LnJhbmdlIDwtIGMoMC4xLCAwLjI1LCAxLCAyLCAzKSAjIFNpZ25hbCB3aWR0aA0KQS50cnVlIDwtIDIgIyBTaWduYWwgYW1wbGl0dWRlDQpCLnRydWUgPC0gMSAjIEJhY2tncm91bmQgYW1wbGl0dWRlDQpEZWx0YS50IDwtIDUgIyBFeHBvc3VyZSB0aW1lDQoNCiMgU2FtcGxpbmcgZ3JpZCBmb3IgY29tcHV0aW5nIHBvc3Rlcmlvcg0KYWxpbSA8LSBjKDAuMCwgNC4wKQ0KYmxpbSA8LSBjKDAuNSwgMS41KQ0KTnNhbXAgPC0gMTAwDQp1bmlHcmlkIDwtIHNlcShmcm9tPTEvKDIqTnNhbXApLA0KdG89MS0xLygyKk5zYW1wKSwgYnk9MS9Oc2FtcCkNCmRlbHRhX2EgPC0gZGlmZihhbGltICkvIE5zYW1wDQpkZWx0YV9iIDwtIGRpZmYoYmxpbSApLyBOc2FtcA0KYSA8LSBhbGltWzFdICsgZGlmZihhbGltICkqIHVuaUdyaWQNCmIgPC0gYmxpbVsxXSArIGRpZmYoYmxpbSApKiB1bmlHcmlkDQoNCiMgTG9nIHBvc3Rlcmlvcg0KbG9nLnBvc3QgPC0gZnVuY3Rpb24oZCwgeCwgYSwgYiwgeDAsIHcsIHQpIHsNCiAgaWYoYTwwIHx8IGIgPDApIHtyZXR1cm4oLUluZiApfSAjIHRoZSBlZmZlY3Qgb2YgdGhlIHByaW9yDQogIHN1bShkcG9pcyhkLCBsYW1iZGE9c2lnbmFsKHgsIGEsIGIsIHgwLCB3LCB0KSwgbG9nPVRSVUUpKQ0KfQ0KDQojIEdlbmVyYXRlIHRoZSBvYnNlcnZlZCBkYXRhDQpzZXQuc2VlZCgxMjMpDQpmb3IgKHcgaW4gdy5yYW5nZSl7DQogIHhkYXQgPC0gc2VxKGZyb209LTcqdywgdG89Nyp3LCBieT0wLjUqdykNCiAgDQogIHMudHJ1ZSA8LSBzaWduYWwoeGRhdCAsIEEudHJ1ZSAsIEIudHJ1ZSAsIHgwLCB3LCBEZWx0YS50KQ0KICBkZGF0IDwtIHJwb2lzKGxlbmd0aChzLnRydWUpLCBzLnRydWUpDQogIHhwbG90IDwtIHNlcShmcm9tPW1pbih4ZGF0KSwgdG89bWF4KHhkYXQpLCBieT0wLjA1KncpDQogIHNwbG90IDwtIHNpZ25hbCh4cGxvdCAsIEEudHJ1ZSAsIEIudHJ1ZSAsIHgwLCB3LCBEZWx0YS50KQ0KICBvcHRpb25zKHJlcHIucGxvdC53aWR0aD0xNCwgcmVwci5wbG90LmhlaWdodD0xMCkgICN0byBzZXQgZ3JhcGggc2l6ZQ0KICBwYXIobWZyb3c9YygxLDIpKQ0KICBwbG90KHhwbG90ICwgc3Bsb3QgLCB4bGFiPSJ4IiwgeWxhYj0iU2lnbmFsK0JhY2tncm91bmQgY291bnRzIiwgeWxpbT1jKDIsIDI0KSkNCiAgI3BhcihuZXc9VFJVRSkNCiAgeGRhdC5vZmYgPC0geGRhdCAtIDAuMjUNCiAgbGluZXMoeGRhdC5vZmYsIGRkYXQgLCB0eXBlPSdzJyxjb2w9J2ZpcmVicmljazMnLCBsd2Q9Mix4bGltPXJhbmdlKHhwbG90KSwgeWxpbT1yYW5nZShjKHNwbG90ICwgZGRhdCApKSkNCiAgDQogICMgQ29tcHV0ZSBsb2cgdW5ub3JtYWxpemVkIHBvc3RlcmlvciAsIHogPSBsbiBQy4YqKGEsYnxEKSwgb24gYSByZWd1bGFyIGdyaWQNCiAgeiA8LSBtYXRyaXgoZGF0YT1OQSAsIG5yb3c9bGVuZ3RoKGEpLCBuY29sPWxlbmd0aChiKSkNCiAgZm9yKGogaW4gMTpsZW5ndGgoYSkpIHsNCiAgICBmb3IoayBpbiAxOmxlbmd0aChiKSkgew0KICAgICAgeltqLGtdIDwtIGxvZy5wb3N0KGRkYXQgLCB4ZGF0ICwgYVtqXSwgYltrXSwgeDAsIHcsIERlbHRhLnQpDQogICAgfQ0KICB9DQogIHogPC0geiAtIG1heCh6KSAjIHNldCBtYXhpbXVtIHRvIHplcm8NCiAgIyBQbG90IHVubm9ybWFsaXplZCAyRCBwb3N0ZXJpb3IgYXMgY29udG91cnMuDQogIGNvbnRvdXIoYSwgYiwgZXhwKHopLA0KICAgICAgICAgIG5sZXZlbHMgPSA1LA0KICAgICAgICAgIGxhYmNleCA9IDAuNSwNCiAgICAgICAgICBsd2QgPSAyLA0KICAgICAgICAgIHhsYWI9ImFtcGxpdHVkZSAsIEEiLA0KICAgICAgICAgIHlsYWI9ImJhY2tncm91bmQgLCBCIikNCiAgYWJsaW5lKHY9MixoPTEsY29sPSJncmV5IikNCn0NCg0KDQpgYGANCg0KKGIpIGNoYW5nZSB0aGUgcmF0aW8gQS9CIHVzZWQgdG8gc2ltdWxhdGUgdGhlIGRhdGEgKGtlZXBpbmcgYm90aA0KICAgIHBvc2l0aXZlIGluIGFjY29yZGFuY2Ugd2l0aCB0aGUgcHJpb3IpIOKAoiBDaGVjayB0aGUgZWZmZWN0IG9uIHRoZQ0KICAgIHJlc3VsdHMNCg0KYGBge3J9DQoNCiMgRGVmaW5lIG1vZGVsIHBhcmFtZXRlcnMNCngwIDwtIDAgIyBTaWduYWwgcGVhaw0Kdy5yYW5nZSA8LSAxICMgU2lnbmFsIHdpZHRoDQpBLnRydWUgPC0gNCAjIFNpZ25hbCBhbXBsaXR1ZGUNCkIudHJ1ZSA8LSAxICMgQmFja2dyb3VuZCBhbXBsaXR1ZGUNCkRlbHRhLnQgPC0gNSAjIEV4cG9zdXJlIHRpbWUNCg0KeGRhdCA8LSBzZXEoZnJvbT0tNyp3LCB0bz03KncsIGJ5PTAuNSp3KQ0KICANCnMudHJ1ZSA8LSBzaWduYWwoeGRhdCAsIEEudHJ1ZSAsIEIudHJ1ZSAsIHgwLCB3LCBEZWx0YS50KQ0KZGRhdCA8LSBycG9pcyhsZW5ndGgocy50cnVlKSwgcy50cnVlKQ0KeHBsb3QgPC0gc2VxKGZyb209bWluKHhkYXQpLCB0bz1tYXgoeGRhdCksIGJ5PTAuMDUqdykNCnNwbG90IDwtIHNpZ25hbCh4cGxvdCAsIEEudHJ1ZSAsIEIudHJ1ZSAsIHgwLCB3LCBEZWx0YS50KQ0Kb3B0aW9ucyhyZXByLnBsb3Qud2lkdGg9MTQsIHJlcHIucGxvdC5oZWlnaHQ9MTApICAjdG8gc2V0IGdyYXBoIHNpemUNCnBhcihtZnJvdz1jKDEsMikpDQpwbG90KHhwbG90ICwgc3Bsb3QgLCB4bGFiPSJ4IiwgeWxhYj0iU2lnbmFsK0JhY2tncm91bmQgY291bnRzIiwgeWxpbT1jKDAsIDQwKSkNCiNwYXIobmV3PVRSVUUpDQp4ZGF0Lm9mZiA8LSB4ZGF0IC0gMC4yNQ0KbGluZXMoeGRhdC5vZmYsIGRkYXQgLCB0eXBlPSdzJyxjb2w9J2ZpcmVicmljazMnLCBsd2Q9Mix4bGltPXJhbmdlKHhwbG90KSwgeWxpbT1yYW5nZShjKHNwbG90ICwgZGRhdCApKSkNCg0KIyBDb21wdXRlIGxvZyB1bm5vcm1hbGl6ZWQgcG9zdGVyaW9yICwgeiA9IGxuIFDLhiooYSxifEQpLCBvbiBhIHJlZ3VsYXIgZ3JpZA0KeiA8LSBtYXRyaXgoZGF0YT1OQSAsIG5yb3c9bGVuZ3RoKGEpLCBuY29sPWxlbmd0aChiKSkNCmZvcihqIGluIDE6bGVuZ3RoKGEpKSB7DQogIGZvcihrIGluIDE6bGVuZ3RoKGIpKSB7DQogICAgeltqLGtdIDwtIGxvZy5wb3N0KGRkYXQgLCB4ZGF0ICwgYVtqXSwgYltrXSwgeDAsIHcsIERlbHRhLnQpDQogIH0NCn0NCnogPC0geiAtIG1heCh6KSAjIHNldCBtYXhpbXVtIHRvIHplcm8NCiMgUGxvdCB1bm5vcm1hbGl6ZWQgMkQgcG9zdGVyaW9yIGFzIGNvbnRvdXJzLg0KY29udG91cihhLCBiLCBleHAoeiksDQogICAgICAgIG5sZXZlbHMgPSA0LA0KICAgICAgICBsYWJjZXggPSAwLjUsDQogICAgICAgIGx3ZCA9IDIsDQogICAgICAgIHhsYWI9ImFtcGxpdHVkZSAsIEEiLA0KICAgICAgICB5bGFiPSJiYWNrZ3JvdW5kICwgQiIsDQogICAgICAgIHhsaW0gPSBjKDAsNSkpDQphYmxpbmUodj00LGg9MSxjb2w9ImdyZXkiKQ0KDQoNCmBgYA0K